/// <reference path="../../typings/blockly.d.ts" />
import React, { createRef, Component } from 'react';
import AceEditor from "react-ace";
import { SpawnOptionsWithoutStdio, spawn } from 'child_process';
import "ace-builds/src-noconflict/mode-python";
import "ace-builds/src-noconflict/theme-terminal";
import { Row, Col } from 'antd';
import { Python } from './index'
import './block.css'
import Events = Blockly.Events



const toolbox = document.getElementById("toolbox")


const obj: Blockly.BlocklyOptions = Object.assign(
  {},
  {
    css: true,
    media: './static/blocks-media/',
    toolbox: toolbox ? toolbox : '',
    zoom: {
      controls: true,
      wheel: true,
      startScale: 1.0
    },
    grid: {
      spacing: 40,
      length: 2,
      colour: "#ddd"
    },
    colours: {
      workspace: "#F9F9F9",
      flyout: "#F9F9F9",
      toolbox: "#FFFFFF",
      toolboxSelected: "#E9EEF2",
      scrollbar: "#CECDCE",
      scrollbarHover: "#CECDCE",
      insertionMarker: "#000000",
      insertionMarkerOpacity: 0.2,
      fieldShadow: "rgba(255, 255, 255, 0.3)",
      dragShadowOpacity: 0.6
    },
    trashcan: false,
  }
);





type Props = {
  currentfile: {
    name?: string,
    value?: string
  },
  saveCode: (name: string, xml: string, py: string) => void,
  fontSize?: number
}
type State = {
  msg: string[],
  value: string,
  workspace?: Blockly.WorkspaceSvg
}


export default class Block extends Component<Props, State> {
  myref: React.RefObject<HTMLDivElement>;
  constructor(porps: Props) {
    super(porps)
    this.myref = createRef<HTMLDivElement>()
    this.state = {
      msg: [],
      value: '',
      workspace: undefined
    }
    this.onChange = this.onChange.bind(this)

  }


  resxml() {

  }

  componentDidMount() {
    const { myref } = this
    const dom = myref.current ? myref.current : '<div></div>'
    const workspace = Blockly.inject(dom, obj);
    (window as any).ex = workspace
    this.setState({
      workspace
    })
    Blockly.svgResize(workspace);
    workspace.addChangeListener(this.onChange);
    const ace = document.querySelector<HTMLDivElement>('#UNIQUE_ID_OF_DIV .ace_gutter')
    if (ace) {
      ace.addEventListener('touchstart', () => {
        ace.addEventListener('touchmove', (ev) => {
          const x = document.querySelector<HTMLDivElement>('#editor .resizerelative')
          if (x) {
            x.style.width = window.innerWidth - ev.touches[0].clientX + 'px'
          }
        })
      }, false)

      ace.addEventListener('touchend', () => {
        ace.removeEventListener('touchmove', () => { }, false)
      }, false)
    }
  }

  componentDidUpdate(prevProps: Props, _prevState: State) {
    const { currentfile, saveCode } = prevProps
    const { value } = this.state
    // 保存之前code
    if (currentfile.name && _prevState.value && _prevState.value !== value) {
      let xmlDom = Blockly.Xml.workspaceToDom(Blockly.mainWorkspace);
      let xmlText = Blockly.Xml.domToPrettyText(xmlDom);
      saveCode(currentfile.name, xmlText, value)
    }

    if (currentfile.value !== this.props.currentfile.value) {
      Blockly.mainWorkspace.clear();
      let xml = Blockly.Xml.textToDom(this.props.currentfile.value ? this.props.currentfile.value : '<xml></xml>')
      Blockly.Xml.appendDomToWorkspace(xml, Blockly.mainWorkspace);
    }
  }

  componentWillUnmount() {
    this.setState({
      workspace: undefined
    })
  }

  repl(name: string, option?: SpawnOptionsWithoutStdio) {

    const r = spawn(name, option)
    r.stdout.on('data', (data) => {
      const { msg } = this.state
      msg.push(data)
      this.setState({
        msg
      })
    })

    r.stdout.on('error', (error) => {
      const { msg } = this.state
      msg.push(error.message)
      this.setState({
        msg
      })
    })

    r.stdout.on('close', () => {
      const { msg } = this.state
      msg.push('已结束')
      this.setState({
        msg
      })
    })

  }

  onChange(event: any) {
    if (event.type == Events.UI) return; // Don't update UI events.
    let python: Blockly.Generator = Python(Blockly)
    let value = python.workspaceToCode(Blockly.mainWorkspace);
    value = `#!/usr/bin/env python\r#-*- coding: UTF-8 -*-\r\r${value}
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    `
    this.setState({
      value
    })
  }

  render() {
    const { myref } = this
    const { value } = this.state
    const { fontSize = 14 } = this.props
    return <Row>
      <Col span={24} >
        <div ref={myref} id="block" ></div>
      </Col>
      <div id="editor" >
        <div className="position-relative">
          <div className="resizerelative"></div>
          {/* <div className="resize-line"></div> */}
          <div className="editor">
            <AceEditor
              mode="python"
              theme="terminal"
              name="UNIQUE_ID_OF_DIV"
              value={value}
              height="645px"
              fontSize={fontSize}
              onChange={(value) => this.setState({ value })}
              editorProps={{ $blockScrolling: true }}
            />
          </div>

        </div>

      </div>
    </Row>
  }
}
